package org.gd.hellojavacore.patterns.composite;

import org.gd.hellojavacore.patterns.StructurePattern;

import java.util.ArrayList;
import java.util.List;

/**
 <pre>

 Компоновщик (англ. Composite pattern) — шаблон проектирования, относится к структурным паттернам,
 объединяет объекты в древовидную структуру для представления иерархии от частного к целому.
 Компоновщик позволяет клиентам обращаться к отдельным объектам и к группам объектов одинаково

 Цель

 Паттерн определяет иерархию классов, которые одновременно могут состоять из примитивных и сложных объектов,
 упрощает архитектуру клиента, делает процесс добавления новых видов объекта более простым

 </pre>
 */
public class Composite implements StructurePattern {

    public static void main(String[] args) {
        //Initialize four ellipses
        Ellipse ellipse1 = new Ellipse();
        Ellipse ellipse2 = new Ellipse();
        Ellipse ellipse3 = new Ellipse();
        Ellipse ellipse4 = new Ellipse();

        //Initialize three composite graphics
        CompositeGraphic graphic = new CompositeGraphic();
        CompositeGraphic graphic1 = new CompositeGraphic();
        CompositeGraphic graphic2 = new CompositeGraphic();

        //Composes the graphics
        graphic1.add(ellipse1);
        graphic1.add(ellipse2);
        graphic1.add(ellipse3);

        graphic2.add(ellipse4);

        graphic.add(graphic1);
        graphic.add(graphic2);

        //Prints the complete graphic (four times the string "Ellipse").
        graphic.print();
    }
}

/**
 * "Component"
 */
interface Graphic {

    /**
     * Prints the graphic.
     */
    public void print();

}

/**
 * "Composite"
 */
class CompositeGraphic implements Graphic {

    /**
     * Collection of child graphics.
     */
    private List<Graphic> mChildGraphics = new ArrayList<Graphic>();

    /**
     * Prints the graphic.
     */
    public void print() {
        for (Graphic graphic : mChildGraphics) {
            graphic.print();
        }
    }

    /**
     * Adds the graphic to the composition.
     *
     * @param graphic Graphic
     */
    public void add(Graphic graphic) {
        mChildGraphics.add(graphic);
    }

    /**
     * Removes the graphic from the composition.
     *
     * @param graphic Graphic
     */
    public void remove(Graphic graphic) {
        mChildGraphics.remove(graphic);
    }

}


/**
 * "Leaf"
 */
class Ellipse implements Graphic {

    /**
     * Prints the graphic.
     */
    public void print() {
        System.out.println("Ellipse");
    }

}
